home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
utils
/
inttools
/
hook.asm
< prev
next >
Wrap
Assembly Source File
|
1995-04-20
|
9KB
|
299 lines
;
; Program to attatch a given interrupt vector to a specific address
; Version One, Steve Kemp '95
;
; Operation, either
;
; HOOK [/?]
; or
; HOOK intnumber segment:offset *** ALL NUMBERS IN HEX
;
; Basically this routine was cobbled together in an hour from the Intview
; program, as such it is not the best way to do things, and is subject to
; strange input requirements... eg HOOK 21 0000:0000 not 0:0, and
; and HOOK 0F 1234:1234 not HOOK F 1234:1234
parser:
mov SI,80h
parse_loop:
inc SI ; Get ready for next character
mov Dl,[SI] ; Get character from command tail
cmp Dl,'/' ; Switch??
jz found_slash ; If so goto switch routine
cmp Dl,0Dh ; End of tail??
jnz parse_loop ; If not repeat
cmp SI,81h ; Still at start of tail??
jnz parameters_entered ; If not continue
mov DX,info_message ; Else queue up error message
call print_string ; Print it
jmp return2DOS ; and return to DOS
parameters_entered:
call calculate_numbers ; Calculate numbers on command line
call print_confirm ; Print out the question info.
mov Ah,08h ; get a keypress
int 21h ; Here
or Al,32 ; Convert it to lowercase
cmp Al,'y' ; Was it a 'Yes'
jz hook_interrupt ; If so go ahead
mov DX,fail_mess ; Get ready to print 'Aborted' message
call print_string ; Do it,
jmp return2DOS ; then eturn to DOS
hook_interrupt:
mov AX,0004 ; Multiply the int. number by four
mov BX,[int_number]
mul BX ; Now!
mov SI,AX ; Point index to correct location in
mov CX,[segment_buffer] ; table, get values to insert
mov BX,[offset_buffer]
cli ; Stop all ints.
push DS ; Save the data segment
sub AX,Ax ; AX=0000
push AX
pop DS ; DS=0000
mov [DS:SI],BX ; Update the offset entry
inc SI
inc SI
mov [DS:SI],CX ; And the segment
pop DS ; Restore the segment
sti ; Enable the maskable ints again.
mov DX,finished_mess ; Tell user we did it
call print_string
jmp return2DOS
found_slash:
inc SI ; Point to next letter
mov Dl,[SI] ; Get it into Dl
cmp Dl,'?' ; ? ?? If so print info about program
jz info
push DX ; Otherwise invalid switch. Save it
mov DX,invalid_switch ; Print invalid switch message
call print_string ; Here
pop DX ; Get back saved letter
add Dl,'A'-'a' ; Print uppercase version of letter
mov Ah,02 ; Print a single character
int 21h ; Now!
return2DOS:
mov Ah,4ch ; Return to DOS
int 21h ; There!
info:
mov DX,info_message ; Point to info. string
call print_string ; Print the string
jmp return2DOS ; finished!
;
; This routine calculates the parameters from the command line.
; They MUST be in the correct format. Code could be improved here a lot
; ... version two ...
calculate_numbers:
mov SI,82h ; Number is first parameter on Command
mov DI,ascii_buffer ; Put a copy of it into the temporary
movsw ; buffer
movsw
push SI ; Save position
; [Calculating the int number here]
mov SI,ascii_buffer ; Point to int_number
call hex_number ; Convert it to a number
mov DX,[temp] ; Get it from the store
mov [int_number],DX ; where it was placed, and put it in the
; interrupt number store
; [Calculating Segment now]
pop SI ; Get back the pointer to the
dec SI ; command line, point to the next byte
push SI ; Save the pointer
call hex_number ; Work out the high byte.
mov dx,[temp] ; Get the result
mov Dh,Dl ; Put the high byte in the right place
mov [segment_buffer],dx ; Store it in the store
pop SI ; Get back the pointer
inc SI ; Point to the low-byte digits
inc SI
push SI ; Save pointer on the stack
call hex_number ; Work out the low-byte
mov dx,[temp] ; Get it from the store
mov ax,[segment_buffer] ; Get the previously calculated hb
mov dh,ah ; Form the word
mov [segment_buffer],dx ; Finished, put the word in the store
; [Calculating the offset now]
pop SI ; Get our pointer back
inc SI ; Point past the low segment byte
inc SI
inc SI ; And the deliminator
push SI ; Save pointer for later
call hex_number ; Work out high byte
mov dx,[temp] ; get the result
mov Dh,Dl ; Put high byte in the right place
mov [offset_buffer],dx ; which is the offset_buffer
pop SI ; Get back the pointer
inc SI ; increase to point to the low byte's
inc SI ; digits
call hex_number ; Calculate them.
mov dx,[temp] ; Add up the high, and low bytes
mov ax,[offset_buffer]
mov dh,ah
mov [offset_buffer],dx ; Stick result in the store..
ret ; Finished calculating parameters
;
; Routine to turn a ascii value into a number. Result put in [Temp]
;
hex_number:
mov Dl,[SI] ; Get a character
inc SI ; Move pointer up by one
mov Dh,[SI] ; Get another character
or Dh,32 ; Convert secont character to lower case
cmp Dh,'h' ; Is it a 'h'
jz one_digit_hex ; If so number is one ASCII-byte long
two_digit_hex: ; Else it MUST be two ASCII-bytes long
cmp Dl,'9'
jle less_than_nine_1 ; Is it a number??
or Dl,32 ; If not its a letter, lowercase it becomes
sub dl,'a'-10-'0' ; Adjust value
less_than_nine_1:
sub Dl,'0' ; Convert it to number 0-15
mov AX,16 ; Get ready to multiply by 16
mov Dh,00
mul DX ; Do it! (Result in AX)
push AX ; Save result on stack
mov Dl,[SI] ; Get next digit
call one_digit_hex ; Treat it as a one digit number
pop AX ; Restore the value that we saved
add AX,DX ; Add high+low results
mov [temp],AX ; Finally store the result in the bufffer
ret ; Finished (Phew!)
one_digit_hex:
cmp Dl,'9' ; Is it a digit??
jle less_than_nine_2 ; If so goto digit routine
or dl,32 ; Convert letter to lower case
sub Dl,'a'-'9'-1 ; Adjust it
less_than_nine_2:
sub Dl,'0' ; Convert it to a number 0-15
mov Dh,00 ; Blank out high byte
mov [temp],DX ; Store in the buffer
ret ; Return
;
; This routine prints the contents of Ah as a two-byte hex number.
;
print_hex:
mov al,ah
shr ah,1
shr ah,1
shr ah,1
shr ah,1
cmp ah,9
jbe next1
add ah,7
next1:
add ah,'0'
and al,0fh
cmp al,9
jbe next2
add al,7
next2:
add al,'0'
push cx
mov cl,ah
mov ch,al
mov Ah,02
mov Dl,cl
int 21h
mov Ah,02
mov Dl,ch
int 21h
pop cx
ret
print_confirm:
mov DX,first_message ; Print first part of message
call print_string ; now!
mov ax,[int_number] ; print int number
mov ah,al
call print_hex ; Here
mov DX,second_message ; print more message
call print_string ; here
print_segment: ; Print the segment
mov DX,[segment_buffer] ; Get a copy of the segment address
push DX ; Save it onto the stack
mov Ah,Dh ; Get ready to print the high byte
call print_hex ; Do it!
pop DX ; Retore the value
mov Ah,Dl ; Print the low byte
call print_hex ; Here
mov ah,2 ; Print a single character
mov Dl,':' ; A seperator
int 21h ; Now!
print_offset:
mov DX,[offset_buffer] ; Get a copy of the segment offset
push DX ; Save it onto the stack
mov Ah,Dh ; Get ready to print the high byte
call print_hex ; Do it!
pop DX ; Retore the value
mov Ah,Dl ; Print the low byte
call print_hex ; Here
mov Ah,02 ; Print a single character
mov Dl,'?' ; A question mark
int 21h ; Now!
ret ; Return
print_string:
mov Ah,09h ; Get ready to output the string addressed
int 21h ; By DX. Do it.
ret ; Return
; **************************************************************************
; * Output Strings and Data area *
; ********************************
invalid_switch:
db "Invalid switch - /","$"
info_message:
db "HOOK Version One - Steven Kemp 1995",0ah,0dh
db " Usage",0ah,0dh
db " HOOK [/?] - Gives this info.",0ah,0dh
db " Or",0ah,0dh
db " HOOK xx ssss:oooo - Hooks int. number xx (hex), to",,0ah,0dh
db " segment ssss, offset oooo.",0ah,0dh
db 0ah,0dh
db " ALL NUMBERS MUST BE IN FULL HEX, e.g. HOOK 0F 1234:0001"
db "$"
first_message:
db " REALLY hook the int ","$"
second_message:
db "h handler to ","$"
fail_mess:
db 0ah,0dh,"Hook operation cancelled at users request.","$"
finished_mess:
db 0ah,0dh,"Interrupt hooked.","$"
ascii_buffer:
db 00,00,00
temp:
dw 0000
int_number:
dw 0000h
offset_buffer:
dw 0000h
segment_buffer:
dw 0000h